﻿using Peer.Game;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;

namespace Peer.Game.Server
{
    public delegate Task<object> OnReceiveEvent(PeerStream peer, OperationRequest request);

    public class PeerConnectionManager : IDisposable
    {
        private readonly List<PeerConnection> connections = new List<PeerConnection>();
        private readonly PeerServer peerServer;
        public event OnReceiveEvent OnReceive;
        public event EventHandler<PeerException> OnError;

        public PeerConnectionManager(string cipher, int port, AddressFamily family = AddressFamily.InterNetwork)
        {
            peerServer = new PeerServer(cipher, new IPEndPoint(IPAddress.Any, port), family);
            peerServer.OnAccept += PeerServer_OnAccept;
        }

        public void Listen()
        {
            peerServer.Listen();
        }

        private void PeerServer_OnAccept(object sender, PeerStream e)
        {
            connections.Add(new PeerConnection(e));
            e.OnDisconnect += OnDisconnect;
            e.OnError += OnError;
            e.OnReceive += Peer_OnReceive;
            Console.WriteLine("连接，连接数：{0}", connections.Count);
        }

        private PeerResponse Peer_OnReceive(PeerStream peer, PeerRequest request)
        {
            var response = OnReceive?.Invoke(peer, new OperationRequest(request.GetBytes()));
            if (response == null)
            {
                return request.CreateResponse();
            }

            return request.CreateResponse();
        }

        private void OnDisconnect(object sender, PeerStream e)
        {
            Remove(e.Id);
            Console.WriteLine("断开，连接数：{0}", connections.Count);
            e.OnDisconnect -= OnDisconnect;
            e.OnError -= OnError;
            e.OnReceive -= Peer_OnReceive;
        }

        public void Remove(Guid guid)
        {
            connections.RemoveAll(a => a.Guid == guid);
        }

        public IPeerSession All()
        {
            return new PeerSession(connections);
        }

        public IPeerSession Group(string groupName)
        {
            if (string.IsNullOrEmpty(groupName))
            {
                return All();
            }
            return new PeerSession(connections.Where(a => a.Is(groupName)));
        }

        public void Dispose()
        {
            peerServer.Dispose();
            GC.SuppressFinalize(this);
        }
    }
}
